#include "settings.h"

// サンプリング用バッファ
int bufCurrentL1[NUMBER_OF_SAMPLES];
int bufCurrentL2[NUMBER_OF_SAMPLES];
int bufVoltage[NUMBER_OF_SAMPLES];

/**
 * 引数で指定された開始時刻と終了時刻がサンプリング間隔以上経過しているかチェックをおこなう
 */
boolean isElapsedSamplingPeriod(unsigned long startMicroSec, unsigned long endMicroSec)
{
  boolean result = false;
  // 経過時間(マイクロ秒)
  unsigned long elapsedMicroSec;
  
  if(startMicroSec <= endMicroSec)
  {
    elapsedMicroSec = endMicroSec - startMicroSec;
  }
  // カウンタ値がオーバーフローを起こしている場合
  else
  {
    elapsedMicroSec = (0xFFFFFFFF - startMicroSec) + endMicroSec;
  }
  
  // サンプリング間隔以上経過しているかチェックする
  if (elapsedMicroSec >= SAMPLING_PERIOD)
  {
    result = true;
  }
  
  return result;
}

/**
 * 1周期分のサンプリングを実施する
 * ※グローバル変数 bufCurrentL1[], bufCurrentL2[], bufVoltage[]に結果を格納する
 */
void doOneFreqSampling()
{
  unsigned long t1, t2;
  int i, r, a1, a2, v;
  int maxVol, minVol;
  int maxA1, minA1;
  int maxA2, minA2;

  // 計測開始時間を取得する
  t1 = micros();

  // １周期分のAD値をサンプリング
  for(i = 0; i < NUMBER_OF_SAMPLES; i++) 
  {
    // AD0ch : 基準電圧値
    r  = analogRead(0);
    // AD1ch : ライン1電流値
    a1 = analogRead(1);
    // AD2ch : ライン2電流値
    a2 = analogRead(2);
    // AD3ch : 電圧値
    v = analogRead(3);
    
    bufCurrentL1[i] = a1 - r;
    bufCurrentL2[i] = a2 - r;
    bufVoltage[i] = v - r;
    if (i == 0)
    {
      maxA1 = bufCurrentL1[0];
      minA1 = bufCurrentL1[0];
      maxA2 = bufCurrentL2[0];
      minA2 = bufCurrentL2[0];
      maxVol = bufVoltage[0];
      minVol = bufVoltage[0];
    } 
    else 
    {
      // ライン1最大電流値(A/D)の更新
      if(maxA1 < bufCurrentL1[i])
      {
        maxA1 = bufCurrentL1[i];
      }
      // ライン1最小電流値(A/D)の更新
      if(bufCurrentL1[i] < minA1)
      {
        minA1 = bufCurrentL1[i];
      }
      
      // ライン2最大電流値(A/D)の更新
      if(maxA2 < bufCurrentL2[i])
      {
        maxA2 = bufCurrentL2[i];
      }
      // ライン2最小電流値(A/D)の更新
      if(bufCurrentL2[i] < minA2)
      {
        minA2 = bufCurrentL2[i];
      }
      
      // 最大電圧値(A/D)の更新
      if (maxVol < bufVoltage[i])
      {
        maxVol = bufVoltage[i];
      }
      // 最小電圧値(A/D)の更新
      if (bufVoltage[i] < minVol)
      {
        minVol = bufVoltage[i];
      }
    }
    
    // サンプリング間隔が経過するまで待つ
    do {
      t2 = micros();
    } while(!isElapsedSamplingPeriod(t1, t2));
    t1 = t2;
  }
  
  // AD値の補正(電流・電圧の0位置を基準にする)をおこなう
  int offsetA1, offsetA2, offsetVol;
  offsetA1 = 0 - (((maxA1 - minA1) / 2) + minA1);
  offsetA2 = 0 - (((maxA2 - minA2) / 2) + minA2);
  offsetVol = 0 - (((maxVol - minVol) / 2) + minVol);
  for(i = 0; i < NUMBER_OF_SAMPLES; i++)
  {
    bufCurrentL1[i] += offsetA1;
    bufCurrentL2[i] += offsetA2;
    bufVoltage[i] += offsetVol;
  }
}

/**
 * 1回分の電力計測をおこなう
 */
void calcWatt ()
{
  int i, j;
  float a1, a2, v;
  float oneFreqPower1, oneFreqPower2;

  // パワーライン1電力積算値
  float integratedPower1 = 0.0;
  // パワーライン2電力積算値
  float integratedPower2 = 0.0;
  
  // 1秒分の電力計測をおこなう
  for (i = 0; i < PWRLINE_FREQ; i++) 
  {
    // 1周期分のサンプリングを実施する
    doOneFreqSampling();
    
    // パワーライン1の1周期分の電力値
    oneFreqPower1 = 0.0;
    // パワーライン2の1周期分の電力値
    oneFreqPower2 = 0.0;
    
    // 1周期分の電力を真の実効値として算出する(積分は台形公式にておこなう)
    for(j = 0; j < NUMBER_OF_SAMPLES; j++)
    {      
      // サンプリングデータから電力を計算する
      a1 = ((float)bufCurrentL1[j] * 5.0 * kCT) / 1024.0;
      a2 = ((float)bufCurrentL2[j] * 5.0 * kCT) / 1024.0;
      v = ((float)bufVoltage[j] * 5.0 * kVT) / 1024.0;
      
      if ((j == 0) || (j == (NUMBER_OF_SAMPLES - 1)))
      {
        oneFreqPower1 += a1 * v / 2.0;
        oneFreqPower2 += a2 * v / 2.0;
      } else {
        oneFreqPower1 += a1 * v;
        oneFreqPower2 += a2 * v;
      }
    }
    
    integratedPower1 += oneFreqPower1;
    integratedPower2 += oneFreqPower2;
  }
  
  if(integratedPower1 > 0.0)
  {
    sample.wrms1 = (long)((integratedPower1 / (float)(PWRLINE_FREQ * NUMBER_OF_SAMPLES))) * 1000;
  }
  if(integratedPower2 > 0.0)
  {
    sample.wrms2 = (long)((integratedPower2 / (float)(PWRLINE_FREQ * NUMBER_OF_SAMPLES))) * 1000;
  }
}

